package org.wso2.carbon.identity.entitlement.axis2handler;



/**
 * Created by IntelliJ IDEA.
 * User: pushpalanka
 * Date: 3/23/11
 * Time: 2:54 PM
 * To change this template use File | Settings | File Templates.
 */


import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.wso2.carbon.core.services.authentication.AuthenticationAdminStub;
import org.wso2.carbon.core.services.authentication.LoginAuthenticationExceptionException;
import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceException;
import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceStub;

import java.rmi.RemoteException;




/*
This class is to forward the taken XACML request to the WSO2 IS which act as PDP here.
 */
public class RequestEvaluatingClient{

    //To keep relevant data of the client so that no need  to login several times in the same session.
    private static String authCookie;

    //URL of the server that provides relevant services. This occasion it is running in the same local host.
    // Identity server, service URL (Always use IP address)
    private final static String BACKEND_SERVER_URL = "https://localhost:9443/services/";

    //The runtime representation of the whole system, to start Axis2 system need to have a configuration context.
    // The lifetime of configuration context will be this of the system, so if you store some state (a property) it
    // will last forever (until system shutdown).
    //Axis2 client needs a configuration context
    private static ConfigurationContext configCtx;









    /*
    Handle log in process of users
     */
    public String sendRequest(String requestString) {
        String decision = "Not logged into server";


        if(login()){

            decision = evaluatePolicy(requestString,setEntitlementServiceParameters()) ;

        }


        return decision;
    }


    private boolean login() {
        //Take input from the command line

//        String userName = null;
//        String password = null;
//        String ip = null;
//        Scanner scanner = new Scanner(System.in);
//
//        System.out.println("Enter Username:");
//        userName = scanner.nextLine();
//        System.out.println("Enter Password:");
//        password = scanner.nextLine();
//        System.out.println("Enter your IP:");
//        ip = scanner.nextLine();


        /*
       set the system properties to enable the https connection
             * Call to https://localhost:9443/services/ uses HTTPS protocol.
             * Therefore need to validate the server certificate. The server certificate is looked up in the
             * trust store. Following code sets what trust-store to look for and its JKs password.
             * Note : The trust store should have server's certificate.
             */

        //Path to Java Key Store (JKS) which is a portable repository of X.509 certificates and private keys  for
        // encrypting/signing some thing with the private key
        String path = "/home/pushpalanka/Installations/wso2is-3.0.1/resources/security/" +
                "wso2carbon.jks";

        // store of CA certificates to trust is trustStore to authenticate remote servers
        System.setProperty("javax.net.ssl.trustStore", path);
        System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");

        try {

            //Create a configuration context. A configuration context contains information for a
            //axis2 environment. This is needed to create an axis2 client
            configCtx = ConfigurationContextFactory.createConfigurationContextFromFileSystem
                    (null, null);
        } catch (AxisFault axisFault) {
            axisFault.printStackTrace();
        }


        boolean authorized = false;
        /**
         * Actual authentication call. If authentication is successful,
         * User can consume the specified services..
         */
//            if (authenticate(userName, password, ip)) {
        if (authenticate("admin", "admin", "127.0.0.0")) {
            System.out.println("admin logged in.");
            authorized = true;
        } else {
            System.out.println("Not allowed to login.");
            authorized = false;
        }
        return authorized;
    }// end of login()



    private String evaluatePolicy(String requestString, EntitlementServiceStub
            entitlementServiceStub) {

        String response = null;
        try {
            response = entitlementServiceStub.getDecision(requestString);
        } catch (java.rmi.RemoteException re) {
            re.printStackTrace();
        }  catch (EntitlementServiceException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        return response;

    }


    /*
    Check whether the combination of user name , IP and password are matching and allowed the requesting access
     */
    private static boolean authenticate(String userName, String password, String remoteIp) {

        //URL of the calling service, to authenticate the user
        String serviceURL = null;


        AuthenticationAdminStub authenticationAdminStub = null;
        boolean isAuthenticated = false;

        serviceURL = BACKEND_SERVER_URL + "AuthenticationAdmin"; //hard coded URL of the service


        System.out.println(userName + " " + password + " " + remoteIp);

        try {
            authenticationAdminStub = new AuthenticationAdminStub(configCtx, serviceURL);
        } catch (AxisFault af) {
            af.printStackTrace();

        }
        //Set session management in enabled state
        authenticationAdminStub._getServiceClient().getOptions().setManageSession(true);

        try {
            //try to login to the system with user information
            isAuthenticated = authenticationAdminStub.login(userName, password, remoteIp);
        } catch (RemoteException re) {
            re.printStackTrace();

        } catch (LoginAuthenticationExceptionException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        //create cookie for future usage in the current session
        authCookie = (String) authenticationAdminStub._getServiceClient()
                .getServiceContext().getProperty(
                        HTTPConstants.COOKIE_STRING);
        return isAuthenticated;
    }//end of authenticate()




    /*
    Create an instance of EntitlementServiceStub class setting required parameter's correctly.
    */
    private EntitlementServiceStub setEntitlementServiceParameters() {
        //URL of the relevant service
        String serviceURL = null;

        ServiceClient client;

        Options option = null;
        EntitlementServiceStub entitlementServiceStub = null;

        serviceURL = BACKEND_SERVER_URL + "EntitlementService";

        try {
            entitlementServiceStub = new EntitlementServiceStub(configCtx, serviceURL);
        } catch (org.apache.axis2.AxisFault af) {
            af.printStackTrace();
        }
        //Get service client implementation used by this stub
        client = entitlementServiceStub._getServiceClient();

        //Get the basic client configuration from this service interaction.
        option = client.getOptions();

        //Set session management in enabled state
        option.setManageSession(true);

        //Assign the created cookie and cookie string for the session
        option.setProperty(org.apache.axis2.transport.http.HTTPConstants.COOKIE_STRING,
                authCookie);


        return entitlementServiceStub;
    }  //end of setEntitlementServiceParameters()




}